package com.sinodata.bsm.center.engine.resource.health;

import java.util.*;

import com.sinodata.bsm.center.bean.RelationHelper;
import com.sinodata.bsm.center.bean.ResBean;
import com.sinodata.bsm.center.cache.*;
import com.sinodata.bsm.center.util.spring.SpringContextHolder;
import com.sinodata.bsm.common.constants.ResConstants;
import com.sinodata.bsm.common.vo.*;
import com.sinodata.bsm.common.constants.EventConstants;

/**
 * 
 * <p>
 * Description: 资源健康度计算
 * </p>
 *
 * @author wangyilin
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * Jul 7, 2012 3:42:26 PM          wangyilin        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class ResHealthCalculate {

    private static NewEventCache newEventCache = SpringContextHolder.getBean(NewEventCache.class);
    private static HealthCalcRuleCache healthCalcRuleCache = SpringContextHolder.getBean(HealthCalcRuleCache.class);
    private static HealthTransRuleCache healthTransRuleCache = SpringContextHolder.getBean(HealthTransRuleCache.class);

    public static int[] getResHealthStatus(Long resId) {
        int[] results = new int[2];
        int healthStatus = 0;
        List<Event> events = newEventCache.getNewEventsByResId(resId);
        int maxEventLevel = EventConstants.LEVEL_NORMAL;
        if (events != null) {
            for (Event e : events) {
                maxEventLevel = Math.max(maxEventLevel, e.getLevel().intValue());
            }
        }
        List<ResBean> children = RelationHelper.children(resId.longValue());
        if (children.size() == 0) {
            results[0] = (6 - maxEventLevel) * 20;
            results[1] = maxEventLevel;
            return results;
        }
        HealthCalcRule rule = healthCalcRuleCache.get(resId);
        if (rule == null) {
            rule = new DefaultHealthCalcRule();
        }
        Map<Long, HealthTransRule> ruleMap = new HashMap<Long, HealthTransRule>();
        float total = 0;
        for (ResBean bean : children) {
            ruleMap.put(bean.res().getId().longValue(), new DefaultHealthTransRule());
            total += 5;
        }
        List<HealthTransRule> transRules = healthTransRuleCache.findChildrenRule(resId);
        if (transRules != null) {
            for (HealthTransRule transRule : transRules) {
                if (!ruleMap.containsKey(transRule.getChildResId().longValue())) {
                    continue;
                }
                ruleMap.put(transRule.getChildResId().longValue(), transRule);
                if (transRule.getIsTrans() == 1) {
                    total = total - 5 + transRule.getWeight();
                } else {
                    total -= 5;
                }

            }
        }
        if (rule.getArithmetic() == ResConstants.AVG_ARITHMETIC) {
            float totalStatus = 0;
            for (ResBean bean : children) {
                HealthTransRule r = ruleMap.get(bean.res().getId().longValue());
                if (r.getIsTrans().intValue() == 0) {
                    continue;
                }
                totalStatus += bean.res().getHealthDegree() * r.getWeight();
            }

            int avg = (int) Math.ceil((totalStatus / total));
            healthStatus = Math.min(avg, (6 - maxEventLevel) * 20);

        } else {
            int minDegree = 100;
            for (ResBean bean : children) {
                HealthTransRule r = ruleMap.get(bean.res().getId().longValue());
                if (r.getIsTrans().intValue() == 0) {
                    continue;
                }
                minDegree = Math.min(minDegree, bean.res().getHealthDegree());
            }
            healthStatus = Math.min(minDegree, (6 - maxEventLevel) * 20);
        }
        int status = ResConstants.NORMAL_USABLE;

        if (healthStatus > 99) {
            status = ResConstants.NORMAL_USABLE;
        } else if (healthStatus > 60) {
            status = ResConstants.BASICAL_USABLE;
        } else if (healthStatus > 40) {
            status = ResConstants.MIDDLE_USABLE;
        } else if (healthStatus > 20) {
            status = ResConstants.FEW_USABLE;
        } else {
            status = ResConstants.NOT_USABLE;
        }
        results[0] = healthStatus;
        results[1] = status;
        return results;

    }
}
